package com.icesoft.mock.builder;

import com.icesoft.core.common.exception.CheckException;
import com.icesoft.core.common.util.JsonUtil;
import com.icesoft.core.common.util.UuidUtil;
import com.icesoft.core.web.helper.http.SignUtil;
import com.icesoft.core.web.model.CryptoPublicKey;
import com.icesoft.core.web.suppose.safehttp.SafeRequestConst;
import com.icesoft.core.web.suppose.safehttp.service.ICryptoService;
import com.icesoft.core.web.suppose.safehttp.service.impl.RsaAesCryptoService;
import com.icesoft.core.web.suppose.safehttp.service.impl.Sm2Sm4CryptoService;
import com.icesoft.mock.base.IMockListener;
import com.icesoft.mock.base.ISafeRequestMockListener;
import lombok.Getter;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.util.Map;

public class SafeRequestMockBuilder extends MockBuilder {
    public static final String USER_TOKEN_NAME = "userToken";
    @Getter
    private String userToken;
    @Getter
    private String sign;
    @Getter
    private String jsonBody;
    private CryptoPublicKey cryptoKey;
    @Getter
    private ICryptoService cryptoService;

    SafeRequestMockBuilder(String url, MockHttpServletRequestBuilder builder) {
        super(url, builder);
    }

    public void setCryptoKey(CryptoPublicKey cryptoKey) {
        this.cryptoKey = cryptoKey;
        if (SafeRequestConst.ALGORITHM_SM.equals(cryptoKey.getAlgorithm())) {
            this.cryptoService = new Sm2Sm4CryptoService();
        } else {
            this.cryptoService = new RsaAesCryptoService();
        }
    }

    public static SafeRequestMockBuilder httpPost(String url) {
        url = resolverUrl(url);
        return new SafeRequestMockBuilder(url, MockMvcRequestBuilders.post(url));
    }

    public SafeRequestMockBuilder safeRequestMockListener(ISafeRequestMockListener safeRequestMockListener) {
        this.mockListener = safeRequestMockListener;
        return this;
    }

    @Override
    public MockBuilder mockListener(IMockListener mockListener) {
        if (!(mockListener instanceof ISafeRequestMockListener)) {
            throw new CheckException("mockListener must instanceof ISafeRequestMockListener");
        }
        return super.mockListener(mockListener);
    }

    public SafeRequestMockBuilder userToken(String userToken) {
        this.userToken = userToken;
        return this;
    }

    @Override
    public MockHttpServletRequestBuilder build() {
        builder.contentType(MediaType.TEXT_PLAIN);
        String nonceStr = UuidUtil.getUUID(16);
        String timeUnit = "" + System.currentTimeMillis();
        headers.put(SignUtil.NONCE_STR_NAME, nonceStr);
        headers.put(SignUtil.TIME_UNIT_NAME, timeUnit);
        sign = SignUtil.sign(params, timeUnit, nonceStr);
        jsonBody = JsonUtil.toJson(params);

        String content = cryptoService.symmetricEncrypt(sign, jsonBody);
        builder.content(content);
        headers.putIfAbsent("versionCode", "2");
        headers.put("clientType", "junitTest");
        headers.put("keyId", cryptoKey.getKeyId());

        String signParam = cryptoService.publicEncrypt(cryptoKey.getPublicKey(), sign);
        headers.put("sign", signParam);

        if (userToken != null) {
            headers.put(USER_TOKEN_NAME, userToken);
        }
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            builder.header(entry.getKey(), entry.getValue());
        }
        return builder;
    }

}
